/**
 * 
 */
package com.arx.script;

import java.util.StringTokenizer;

import com.arx.common.GlobalConsts;
import com.arx.script.flyweight.ScriptObject;
import com.arx.script.flyweight.ScriptVariable;
import com.dalonedrau.pool.PooledStringBuilder;
import com.dalonedrau.pool.StringBuilderPool;

/**
 * @author Donald
 */
abstract class ScriptTextBase extends ScriptObjectBase {
	protected final boolean charIn(final String string, final char _char) {
		boolean in = false;
		if (string.indexOf(_char) >= 0) {
			in = true;
		}
		return in;
	}
	protected final boolean charInIgnoreCase(final String string,
			final char _char) {
		boolean in = false;
		if (string.toUpperCase().indexOf(Character.toUpperCase(_char)) >= 0) {
			in = true;
		}
		return in;
	}
	protected final int CountBrackets(final ScriptObject es) {
		int count = 0;
		for (int i = 0; i < es.getSize(); i++) {
			if (es.getData().charAt(i) == '/'
					&& i < es.getSize() - 1
					&& es.getData().charAt(i + 1) == '/') {
				i = GotoNextLine(es, i);
				if (i == -1) {
					break;
				}
			}
			if (es.getData().charAt(i) == '{') {
				count++;
			}
			if (es.getData().charAt(i) == '}') {
				count--;
			}
		}
		return count;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final int GetNextWord(final ScriptObject es, final int i,
			final String temp) {
		return this.GetNextWord(es, i, temp, 0);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final int GetNextWord(final ScriptObject es, int i, String temp,
			final long flags) {
		int val = -1;
		PooledStringBuilder sb1 =
				StringBuilderPool.getInstance().getStringBuilder();
		if (i >= 0 // Avoid negative position...
				&& i < es.getSize()) { // Avoid position superior to script size
			long tildes = 0; // number of tildes
			int old = i; // stores start pos in old
			super.setLINEEND(false); // Global LINEEND set to 0 (no LINEEND for
										// now)
			long j = 0;
			String esdat = new String(es.getData());
			// First ignores spaces & unused chars
			while (i < es.getSize() &&
					(esdat.charAt(i) <= 32
							|| esdat.charAt(i) == '('
							|| esdat.charAt(i) == ')')) {
				if (esdat.charAt(i) == '\n') {
					super.setLINEEND(true);
				}
				i++;
			}
			// now take chars until it finds a space,
			// parentheses, or unused char
			while (esdat.charAt(i) > 32
					&& esdat.charAt(i) != '('
					&& esdat.charAt(i) != ')') {
				if (esdat.charAt(i) == '"') {
					// found a quote. move char index
					// to just after quote position
					i++;
					if (i >= es.getSize()) {
						// if the quote is at the end of
						// the script data, return -1
						return -1;
					}
					// grab characters within the quotes until
					// we reach either the closing quotes or
					// the line end
					while (esdat.charAt(i) != '"' && !super.isLINEEND()) {
						if (esdat.charAt(i) == '\n') {
							super.setLINEEND(true);
						} else if (esdat.charAt(i) == '~') {
							tildes++;
						}
						sb1.append(esdat.charAt(i));
						i++;

						// if we reached the end of script data, return -1
						if (i >= es.getSize()) {
							temp = sb1.toString();
							sb1.returnToPool();
							return -1;
						}
						j++;
					}
					// put everything within the quotes into temp
					temp = sb1.toString();
					sb1.returnToPool();
					return i + 1;
				} else {
					sb1.append(esdat.charAt(i));
					if (esdat.charAt(i) == '~') {
						tildes++;
					}
					i++;
					if (i >= es.getSize()) {
						temp = sb1.toString();
						sb1.returnToPool();
						return -1;
					}
					j++;
				}
			} // end while
			temp = sb1.toString();
			sb1.returnToPool();
			if (i == old) {
				return -1;
			}
			// Now retreives Tilded chars...
			if ((flags & 2) != 2
					&& tildes > 0) {
				int _pos = 0;
				long _size = temp.length();
				while (_pos < _size && tildes >= 2) {
					if (temp.charAt(_pos) == '~') {
						int start = _pos + 1;
						_pos++;

						while (_pos < _size && temp.charAt(_pos) != '~') {
							_pos++;
						}
						int end = _pos - 1;
						// Found A tilded string...
						if (end > start) {
							String tildedd, interp, result;
							tildedd = temp.substring(start, end);
							/*
							 * memcpy(tildedd, temp + start, end - start + 1);
							 * tildedd[end-start+1] = 0;
							 */
							if (es.getMaster() != null) {
								interp = GetVarValueInterpretedAsText(
										tildedd,
										es.getMaster(),
										super.get_CURIO()
										);
							} else {
								interp = GetVarValueInterpretedAsText(
										tildedd,
										es,
										super.get_CURIO()
										);
							}
							if (start == 1) {
								result = "";
							} else {
								result = temp.substring(0, start);
							}
							result += interp;

							if (end + 2 < _size) {
								result += temp.substring(end + 2);
								// strcat(result, temp + end + 2);
							}
							_pos = -1;
							temp = result;
							_size = temp.length();
							tildes -= 2;
						}
					}
					_pos++;
				}
			}
		} else {
			return -1;
		}
		return i;
	}
	/**
	 * Gets the position of the next line in the {@link ScriptObject}.
	 * @param es the {@link ScriptObject} being parsed
	 * @param pos the current position
	 * @return int
	 */
	protected final int GotoNextLine(final ScriptObject es, int pos) {
		if (es != null && es.getData() != null) {
			while (pos < es.getData().length()
					&& es.getData().charAt(pos) != '\n') {
				pos++;
			}
			if (pos < es.getData().length()) {
				pos++;
			}
		}
		return pos;
	}
	/**
	 * Determines if a specific search string is an element of a larger string.
	 * @param searchString the {@link String} being searched for
	 * @param text the overall {@link String}
	 * @return true if the search string is part of the larger string; false
	 *         otherwise
	 */
	protected final boolean IsElement(final String searchString,
			final String text) {
		boolean is = false;
		StringTokenizer token = new StringTokenizer(text, " ");
		while (token.hasMoreTokens()) {
			if (token.nextToken().equals(searchString)) {
				is = true;
				break;
			}
		}
		return is;
	}
	/**
	 * Determines if a character signals its modifier is a global variable.
	 * @param c the character
	 * @return true if the character is a global modifier; false otherwise
	 */
	protected final boolean isGlobal(final char c) {
		boolean isGlobal = false;
		if (c == '$' || c == '#' || c == '&') {
			isGlobal = true;
		}
		return isGlobal;
	}
	protected final void MakeGlobalText(String tx) {
		for (int i = 0; i < super.getNB_GLOBALS(); i++) {
			PooledStringBuilder sb =
					StringBuilderPool.getInstance().getStringBuilder();
			ScriptVariable sv = super.getGlobalScriptVariable(i);
			if (sv != null) {
				switch (sv.getType()) {
					case GlobalConsts.TYPE_G_TEXT:
						sb.append(tx);
						sb.append(sv.getName());
						sb.append(" = ");
						sb.append(sv.getText());
						sb.append("\r\n");
						tx = sb.toString();
						break;
					case GlobalConsts.TYPE_G_LONG:
						sb.append(tx);
						sb.append(sv.getName());
						sb.append(" = ");
						sb.append(String.format("%d", sv.getIval()));
						sb.append("\r\n");
						tx = sb.toString();
						break;
					case GlobalConsts.TYPE_G_FLOAT:
						sb.append(tx);
						sb.append(sv.getName());
						sb.append(" = ");
						sb.append(String.format("%f", sv.getFval()));
						sb.append("\r\n");
						tx = sb.toString();
						break;
				}
			}
			sb.returnToPool();
		}
	}
	/**
	 * Removes numeric characters from a string and returns that value.
	 * @param text the {@link String}
	 * @return {@link String}
	 */
	protected final String RemoveNumerics(final String text) {
		return new String(text.replaceAll("[0-9]", ""));
	}
	protected final long SkipNextStatement(final ScriptObject es, int pos) {
		String temp = "";
		int brack = 1;
		int tpos;
		pos = GetNextWord(es, pos, temp);
		if (temp.charAt(0) == '{') {
			while (brack > 0) {
				pos = GetNextWord(es, pos, temp);
				if (pos < 0) {
					return -1;
				}
				if (temp.charAt(0) == '{') {
					brack++;
				}
				if (temp.charAt(0) == '}') {
					brack--;
				}
			}
		} else {
			pos = GotoNextLine(es, pos);
		}
		tpos = GetNextWord(es, pos, temp);
		temp = temp.toUpperCase();
		if (temp.equals("ELSE")) {
			pos = tpos;
		}
		return pos;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public final boolean specialstrcmp(final String text, final String seek) {
		int len = seek.length();
		int len2 = text.length();
		boolean compares = true;
		if (len2 < len) {
			compares = false;
		} else {
			for (int i = 0; i < len; i++) {
				if (text.charAt(i) != seek.charAt(i)) {
					compares = false;
				}
			}
		}
		return compares;
	}
}
